/* 
 * File:   matriz.cpp
 * Author: chaterolas
 * 
 * Created on 24 de junio de 2009, 05:02 PM
 */

#include "matriz.h"

/**
 * Crea una instancia de matriz de 3 x 3 con un valor por default en todas sus
 * entradas
 * @param defval (valor por default en cada entrada)
 */
Matriz::Matriz(double defval) {
    matrix = new double[9];

    for(int i = 0; i < 9; i++)
        matrix[i] = defval;
}

/**
 * Crea una instancia de matriz de 3 x 3 apartir de colocar tres vectores en
 * forma de columna
 * @param v1 (vector columna 1)
 * @param v2 (vector columna 2)
 * @param v3 (vector columna 3)
 */
Matriz::Matriz(const Vector3D& v1, const Vector3D& v2, const Vector3D& v3) {
    matrix = new double[9];
    for(int i = 0 ; i < 3; i++) {
        setElement(0, i, v1.coor[i]);
        setElement(1, i, v2.coor[i]);
        setElement(2, i, v3.coor[i]);
    }
}

/**
 * Crea una copia de una matriz ya antes definida
 * @param orig (referencia de la matriz a copiar )
 */
Matriz::Matriz(const Matriz& orig) {
    matrix = new double[9];
    for(int i = 0; i < 9; i++)
        matrix[i] = orig.matrix[i];
}

/**
 * Destruye la instancia que lo llama
 */
Matriz::~Matriz() {
    delete [] matrix;
}

/**
 * Regresa la entrada (ren, col) de la instancia
 * @param ren (renglon)
 * @param col (columna)
 * @return val (valor en la entrada ren, col)
 */
double Matriz::getElement(int ren, int col) {
    return matrix[3*ren + col];
}

/**
 * Asigna el valor val a la entrada (ren,col) de esta matriz.
 * @param ren (renglon)
 * @param col (columna)
 * @param val (nuevo valor de la entrada)
 */
void Matriz::setElement(int ren, int col, double val) {
    matrix[3*ren + col] = val;
}

/**
 * Regresa la matriz resultante de sumar esta matriz con otra
 * @param m (otra matriz)
 * @return matriz (resultante de la suma)
 */
Matriz *Matriz::operator +(const Matriz &m) {
    Matriz *temp = new Matriz();

    for(int r = 0; r < 3; r++) {
        for(int c = 0; c < 3; c++) {
            temp->setElement(r, c, getElement(r, c) + m.matrix[3*r + c]);
        }
    }

    return temp;
}

/**
 * Regresa el resultado de multiplicar esta matriz con otra.
 * @param m (matriz)
 * @return matriz (resultante de la multiplicacion)
 */
Matriz *Matriz::operator *(const Matriz &m) {
    Matriz *temp = new Matriz();
    double valent = 0;

    for(int r = 0; r < 3; r++) {
        for(int c = 0; c < 3; c++) {
            valent = 0;

            for(int k = 0; k < 3; k++)
                valent += getElement(r,k) * m.matrix[3*k + c];

            temp->setElement(r, c, valent);
        }
    }

    return temp;
}


/**
 * Regresa el vector resultante de aplicar esta transformacion al vector v
 * @param v (vector a cambiar de base)
 * @return vector (resultante de aplicar la transformacion)
 */
Vector3D *Matriz::operator *(const Vector3D &v) {
    Vector3D *temp = new Vector3D();
    double valcoor = 0;

    for(int r = 0; r < 3; r++) {
        valcoor = 0;

        for(int c = 0; c < 3; c++)
            valcoor += getElement(r, c) * v.coor[c];

        temp->coor[r] = valcoor;
    }

    return temp;
}

/**
 * Regresa la matriz resultante de trnasponer esta matriz.
 * @return (la matriz transpuesta de esta)
 */
void Matriz::transpose() {
    Matriz *temp = new Matriz();

    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            temp->setElement(i, j, getElement(j, i));

    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            setElement(i, j, temp->getElement(i, j));

    delete temp;
}
